﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using NUnit.Framework;
using IronCow.Rest;
using System.Collections.Specialized;
using System.IO;
using NUnit.Framework.SyntaxHelpers;
using System.Xml;
using System.Net;

namespace IronCow.UnitTests.Mock
{
    public class MockRestClient : IRestClient
    {
        public const string DefaultApiKey = "IronCow.Mock.ApiKey";
        public const string DefaultSharedSecret = "IronCow.Mock.SharedSecret";
        public const string DefaultToken = "IronCow.Mock.Token";

        private static XmlSerializer sResponseSerializer = new XmlSerializer(typeof(Response));

        private int mCurrentResponseIndex = 0;
        private List<string> mScheduledMethods = new List<string>();
        private List<MockResponse> mScheduledResponses = new List<MockResponse>();

        public MockRestClient()
        {
        }

        public void AddResponse(string method, MockResponse response)
        {
            mScheduledMethods.Add(method);
            mScheduledResponses.Add(response);
        }

        public void AddTimelineResponse()
        {
            AddResponse("rtm.timelines.create", new MockSuccessResponse()
            {
                new MockTimelineResponsePart()
            });
        }

        public void EnsureAllResponsesUsed()
        {
            Assert.AreEqual(mScheduledResponses.Count, mCurrentResponseIndex, "Not all mocked responses were used.");
        }

        #region IRestClient Members

        public string ApiKey
        {
            get { return DefaultApiKey; }
        }

        public string SharedSecret
        {
            get { return DefaultSharedSecret; }
        }

        public string AuthToken
        {
            get { return DefaultToken; }
            set { throw new NotImplementedException(); }
        }

        public bool UseHttps { get; set; }

        public int Timeout { get; set; }

        public IWebProxy Proxy { get; set; }

        public TimeSpan Throttling { get; set; }

        public IResponseCache Cache { get; set; }

        public Response GetResponse(string method, Dictionary<string, string> parameters, bool throwOnError)
        {
            Assert.That(mCurrentResponseIndex, Is.LessThan(mScheduledResponses.Count), "All mocked responses have been used.");
            Assert.That(method, Is.EqualTo(mScheduledMethods[mCurrentResponseIndex]), "Expected to answer method '{0}'.", mScheduledMethods[mCurrentResponseIndex]);

            Assert.IsFalse(parameters.ContainsKey("method"), "A parameter named 'method' is already present.");
            parameters.Add("method", method);

            mCurrentResponseIndex++;
            MockResponse mockResponse = mScheduledResponses[mCurrentResponseIndex - 1];
            StringBuilder responseBuilder = new StringBuilder(1024);
            XmlWriterSettings responseWriterSettings = new XmlWriterSettings();
            responseWriterSettings.Indent = true;
            using (XmlWriter responseWriter = XmlWriter.Create(responseBuilder, responseWriterSettings))
            {
                mockResponse.GetResponseMarkup(responseWriter, parameters);
            }
            string responseString = responseBuilder.ToString();

            StringReader responseReader = new StringReader(responseString);
            Response response = (Response)sResponseSerializer.Deserialize(responseReader);
            responseReader.Close();

            if (throwOnError && response.Status != ResponseStatus.OK)
                throw new RtmException(response.Error);
            return response;
        }

        #endregion
    }
}
